#include "Martiale.h"

using namespace std;

/**
 * Constructeur qui initialise tous les champs.
 *
 * @param[in] nom nom de l'arme.
 * @param[in] masse poids de l'arme (en systaxe LaTeX).
 * @param[in] taille taille de l'arme (P, M, G, ...).
 * @param[in] type type de dégâts causé par l'arme (P, T, C).
 * @param[in] vitesse facteur de vitesse de l'arme.
 * @param[in] freq fréquence d'attaque maximale.
 * @param[in] portee portée, applicable pour les armes de jet.
 * @param[in] pm dégâts sur cibles petites et moyennes.
 * @param[in] grand dégâts sur cibles ayant une taille au moins
 * grande.
 * @param[in] aff booléen décidant si la compétence suivante doit être
 * affichée automatiquement (munitions, 1/2 mains).
 * @param[in] large numéro du groupe large.
 * @param[in] restreint numéro du groupe restreint.
 * @param[in] niveau niveau de compétence (spécialisation, maîtrise,
 * ...), les niveaux de spécialisation sont encodés sur les 3 premiers
 * bits, le quatrième indique une arme de prédilection et le cinquième
 * l'expertise martiale.
 */
Martiale::Martiale(const std::string& nom, const std::string masse,
		   const char& taille, const std::string& type,
		   const unsigned& vitesse, const std::string& freq,
		   const std::string& portee, const std::string& pm,
		   const std::string& grand, const bool& aff,
		   const unsigned& large, const unsigned& restreint/*,
		   const unsigned& niveau */)
  : ADDItemObjet( "Martiale", nom ), Poids( masse ), TailleArme( taille ),
    TypeDegats( type ), Vitesse( vitesse ), Frequence( freq ),
    Portee( portee ), DegatsPM( pm ), DegatsG( grand ),
    AfficherSuite( aff ), GroupeLarge( large ),
    GroupeRestreint( restreint )
    /*, NiveauSpec( niveau % 8 ),
      ArmePredilection( niveau & 0x8 ), ExpertiseMartiale( niveau & 0x10 )*/
{}

/**
 * Constructeur de copie.
 *
 * @param[in] mart instance de Martiale à dupliquer.
 */
Martiale::Martiale( const Martiale & mart )
  : ADDItemObjet( "Martiale", mart.nom() ), Poids( mart.poids() ),
    TailleArme( mart.tailleArme() ), TypeDegats( mart.typeDegats() ),
    Vitesse( mart.vitesse() ), Frequence( mart.frequence() ),
    Portee( mart.portee() ), DegatsPM( mart.degatsPM() ),
    DegatsG( mart.degatsG() ), AfficherSuite( mart.afficherSuite() ),
    GroupeLarge( mart.groupeLarge() ),
    GroupeRestreint( mart.groupeRestreint() )// ,
    // NiveauSpec( mart.niveauSpec() ),
    // ArmePredilection( mart.armePredilection() ),
    // ExpertiseMartiale( mart.expertiseMartiale() )
{}

/**
 * Destructeur, ne fait rien de spécial.
 */
Martiale::~Martiale()
{}

/**
 * Opérateur d'affectation, permet de copier une instance dans une
 * autre.
 *
 * @param[in] mart instance de Martiale à copier.
 *
 * @return une référence sur l'instance courante.
 */
Martiale& Martiale::operator=( const Martiale & mart )
{
  setTypeObjet( "Martiale" );
  setNom( mart.nom() );
  Poids = mart.poids();
  TailleArme = mart.tailleArme() ;
  TypeDegats = mart.typeDegats() ;
  Vitesse = mart.vitesse() ;
  Frequence = mart.frequence() ;
  Portee = mart.portee() ;
  DegatsPM = mart.degatsPM() ;
  DegatsG = mart.degatsG() ;
  AfficherSuite = mart.afficherSuite() ;
  GroupeLarge = mart.groupeLarge() ;
  GroupeRestreint = mart.groupeRestreint() ;
  // NiveauSpec = mart.niveauSpec() ;
  // ArmePredilection = mart.armePredilection() ;
  // ExpertiseMartiale = mart.expertiseMartiale() ;

  return *this;
}

/**
 * Permet de comparer deux instances de Martiale. On tire parti de la
 * "lazy evalutation" : on compare premièrement le nom de l'arme, puis
 * les groupes larges et restreints. Ensuite (et si nécessaire) tous
 * les autres champs sont comparés.
 *
 * @param[in] mart instance à comparer avec l'instance courante.
 *
 * @return \e true si les deux instances sont pareilles, \e false
 * sinon.
 */
bool Martiale::operator==( const Martiale & mart ) const
{
  if ( nom() != mart.nom() ||
       groupeLarge() != mart.groupeLarge() ||
       groupeRestreint() != mart.groupeRestreint() ||
       poids() != mart.poids() ||
       tailleArme() != mart.tailleArme() ||
       typeDegats() != mart.typeDegats() ||
       vitesse() != mart.vitesse() ||
       frequence() != mart.frequence() ||
       portee() != mart.portee() ||
       degatsPM() != mart.degatsPM() ||
       degatsG() != mart.degatsG() ||
       afficherSuite() != mart.afficherSuite()/* ||
       niveauSpec() != mart.niveauSpec() ||
       armePredilection() != mart.armePredilection() ||
       expertiseMartiale() != mart.expertiseMartiale() */ )
    return false;
  else
    return true;
}

ostream& operator<<(ostream& os, const Martiale& mart)
{
    os << mart . nom() << " & "
       << mart . poids() << " & "
       << mart . tailleArme() << " & "
       << mart . typeDegats() << " & "
       << mart . vitesse() << " & "
       << mart . frequence() << " & "
       << mart . portee() << " & "
       << mart . degatsPM() << " & "
       << mart . degatsG() << "\\\\";

  return os;
}

/**
 * Réalise un affichage simplifié du contenu de la compétence
 * martiale, dans le but de pouvoir vérifier que la lecture s'est bien
 * effectuée.
 *
 * @param[in] os flot de sortie dans lequel la compétence martiale sera
 * écrite.
 *
 * @return le flot modifié.
 */
ostream& Martiale::afficheTout(ostream& os) const
{
  os << nom() << ' ' << poids() << ' '
     << tailleArme() << ' '<< typeDegats()
     << ' ' << vitesse() << ' ' << frequence() << ' '
     << portee() << ' ' << degatsPM() << ' ' << degatsG()
     << ' ' << ( afficherSuite() ? "true " : "false " )
     << groupeLarge() << ' ' << groupeRestreint();

    return os;
}

/**
 * Réalise un affichage simplifié du contenu de la compétence
 * martiale, dans le but de pouvoir vérifier que la lecture s'est bien
 * effectuée.
 *
 * @param[in] os flot de sortie dans lequel la compétence martiale sera
 * écrite.
 *
 * @return le flot modifié.
 */
FlotMessage& Martiale::afficheTout(FlotMessage& flot) const
{
  flot << nom() << ' ' << poids() << ' '
       << tailleArme() << ' '<< typeDegats()
       << ' ' << vitesse() << ' ' << frequence() << ' '
       << portee() << ' ' << degatsPM() << ' ' << degatsG()
       << ' ' << ( afficherSuite() ? "true " : "false " )
       << groupeLarge() << ' ' << groupeRestreint();
  
  return flot;
}

/**
 * Permet d'accéder à la masse de l'arme.
 *
 * @return une référence constante sur Poids-
 */
const string& Martiale::poids() const
{
  return Poids;
}

/**
 * Permet d'accéder à la taille de l'arme.
 *
 * @return une référence constante sur TailleArme.
 */
const char& Martiale::tailleArme() const
{
  return TailleArme;
}

/**
 * Permet d'accéder au type de dégâts causé par l'arme.
 *
 * @return une référence constante sur TypeDegats.
 */
const string& Martiale::typeDegats() const
{
  return TypeDegats;
}

/**
 * Permet d'accéder au fateur de vitesse de l'arme.
 *
 * @return une référence constante sur Vitesse.
 */
const unsigned& Martiale::vitesse() const
{
  return Vitesse;
}

/**
 * Permet d'accéder au nombre d'attaque par round pour cette arme (ne
 * tient pas compte d'une spécialisation, exprtise martiale, ...).
 *
 * @return une référence constante sur Frequence.
 */
const string& Martiale::frequence() const
{
  return Frequence;
}

/**
 * Permet d'accéder à la portée de l'arme.
 *
 * @return une référence constante sur Portee.
 */
const string& Martiale::portee() const
{
  return Portee;
}

/**
 * Pemet d'accéder aux dégâts infligés à une cible petite ou moyenne.
 *
 * @return une référence constante sur DegatsPM.
 */
const string& Martiale::degatsPM() const
{
  return DegatsPM;
}

/**
 * Permet d'accéder aux dégâts infligé à une grande cible.
 *
 * @return une référence constante sur DegatsG.
 */
const string& Martiale::degatsG() const
{
  return DegatsG;
}

/**
 * Permet d'accéder au champ indiquant si la compétence suivante doit
 * être affichée.
 *
 * @return une référence constante sur AfficherSuite.
 */
const bool& Martiale::afficherSuite() const
{
  return AfficherSuite;
}

/**
 * Permet d'accéder au numéro du groupe large auquel appartient l'arme.
 *
 * @return une référence constante sur GroupeLarge.
 */
const unsigned& Martiale::groupeLarge() const
{
  return GroupeLarge;
}

/**
 * Permet d'accéder au numéro du groupe restretin auquel appartient l'arme.
 *
 * @return une référence constante sur GroupeRestreint.
 */
const unsigned& Martiale::groupeRestreint() const
{
  return GroupeRestreint;
}

// /**
//  * Permet d'accéder 
//  *
//  *
//  */
// const unsigned& Martiale::niveauSpec() const
// {
//   return NiveauSpec;
// }

// const bool& Martiale::armePredilection() const
// {
//   return ArmePredilection;
// }

// const bool& Martiale::expertiseMartiale() const
// {
//   return ExpertiseMartiale;
// }
